'''
Created on Nov 11, 2011

@author: Victor Bos
'''

import copy
import graphics
import utils

FGCOLOUR="colour0"
BGCOLOUR="colour1"
TRANSPARENT=""
DEFAULT_AREA_FGCOLOUR="ghostwhite"
DEFAULT_AREA_BGCOLOUR="lightgray"

def overlapping_areas(a0, a1):
    return (graphics.overlapping_bbox(a0.bbox(), a1.bbox()) and
            graphics.overlapping_polygons(a0.polygon, a1.polygon))

class Area:

    def __init__(self, name, polygon):
        self.name = name
        self.polygon = polygon
        self.poly_idx = 0
        self.gpoint = None
        self.bb = None
        self.attrs = {}
        self.attrs[FGCOLOUR] = DEFAULT_AREA_FGCOLOUR
        self.attrs[BGCOLOUR] = DEFAULT_AREA_BGCOLOUR

    def __cmp__(self, other):
        return cmp(self.name, other.name)

    def __hash__(self):
        return hash(self.name) ^ 5247

    def __copy__(self):
        area = Area(self.name, copy.copy(self.polygon))
        area.poly_idx = self.poly_idx
        area.gpoint = self.gpoint
        area.bb = self.bb
        area.attrs = utils.copydict(self.attrs)        
        return area

    def fgcolour(self):
        return self.attrs.get(FGCOLOUR, DEFAULT_AREA_FGCOLOUR)
    def set_fgcolour(self, colour):
        self.attrs[FGCOLOUR] = colour
    def bgcolour(self):
        return self.attrs.get(BGCOLOUR, DEFAULT_AREA_BGCOLOUR)
    def set_bgcolour(self, colour):
        self.attrs[BGCOLOUR] = colour

    def bbox(self):
        if self.bb is None:
            p0 = self.polygon[0]
            bb = list(p0 + p0)
            for p in self.polygon:
                x, y = p
                if x<bb[0]:
                    bb[0] = x
                if x>bb[2]:
                    bb[2] = x
                if y<bb[1]:
                    bb[1] = y
                if y>bb[3]:
                    bb[3] = y
            self.bb = tuple(bb)

        # debug: check the computation
        # self.check_bbox()

        return self.bb

    def check_bbox(self):
        x0, y0, x1, y1 = self.bb
        for p in self.polygon:
            x, y = p
            assert (x>=x0 and x <= x1)
            assert (y>=y0 and y <= y1)

    def reset_bbox(self):
        self.bb = None
        
    def compute_gravity_point(self):
        if len(self.polygon) == 0:
            self.gpoint = (0, 0)
        bb = self.bbox()
        gpx = (bb[0] + bb[2]) / 2
        gpy = (bb[1] + bb[3]) / 2
        self.gpoint = (gpx, gpy)

    def gravity_point(self):
        if self.gpoint is None:
            self.compute_gravity_point()
        return self.gpoint

    def rotate_poly_idx(self, d):
        self.poly_idx = (self.poly_idx + d) % len(self.polygon)
        
    def incr_poly_idx(self):
        self.rotate_poly_idx(1)

    def decr_poly_idx(self):
        self.rotate_poly_idx(-1)

    def poly_start_point(self):
        if len(self.polygon)>0:
            return self.polygon[self.poly_idx]
        return None

    def set_poly_start_point(self, x, y):
        if len(self.polygon)>0:
            self.polygon[self.poly_idx] = (x, y)
